package com.yuzhenxin.coursesystem.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.framework.common.exception.ServiceException;
import com.yuzhenxin.coursesystem.config.enums.ErrorCodeConstants;
import com.yuzhenxin.coursesystem.controller.selection.vo.SelectionQueryReqVO;
import com.yuzhenxin.coursesystem.entity.ScheduleDO;
import com.yuzhenxin.coursesystem.entity.SelectionDO;
import com.yuzhenxin.coursesystem.entity.StudentDO;
import com.yuzhenxin.coursesystem.mapper.SelectionMapper;
import com.yuzhenxin.coursesystem.service.ScheduleService;
import com.yuzhenxin.coursesystem.service.SelectionService;
import com.yuzhenxin.coursesystem.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

@Service
public class SelectionServiceImpl extends ServiceImpl<SelectionMapper, SelectionDO> implements SelectionService {

    @Autowired
    private SelectionMapper selectionMapper;

    @Autowired
    private ScheduleService scheduleService;

    @Autowired
    private StudentService studentService;

    @Override
    public IPage<SelectionDO> selectPage(SelectionQueryReqVO reqDto) {
        Page<SelectionDO> page = new Page<>(reqDto.getPageNo(), reqDto.getPageSize());
        String studentName = reqDto.getStudentName();
        String courseName = reqDto.getCourseName();
        LambdaQueryWrapper<SelectionDO> queryWrapper = Wrappers.<SelectionDO>lambdaQuery()
                .like(ObjectUtil.isNotEmpty(studentName), SelectionDO::getStudentName, studentName)
                .like(ObjectUtil.isNotEmpty(courseName), SelectionDO::getCourseName, courseName);
        return selectionMapper.selectPage(page, queryWrapper);
    }

    @Override
    public List<Map<String, Object>> selectStudentCount(int current, int limit) {
        return selectionMapper.selectStudentCount(current, limit);
    }

    @Override
    public List<Map<String, Object>> selectCourseCount(int current, int limit) {
        return selectionMapper.selectCourseCount();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void selectCourse(Long studentId, Long scheduleId) {
        // 通过id找到学生和排课信息
        StudentDO studentEntity = studentService.getById(studentId);
        ScheduleDO scheduleDO = scheduleService.getById(scheduleId);

        // 查询该学生是否选过该课程
        LambdaQueryWrapper<SelectionDO> selectionQueryWrapper = Wrappers.<SelectionDO>lambdaQuery()
                .eq(SelectionDO::getStudentNumber, studentEntity.getNumber())
                .eq(SelectionDO::getCourseNumber, scheduleDO.getCourseNumber())
                .eq(SelectionDO::getTeacherName, scheduleDO.getTeacherName());
        SelectionDO selectionDO = selectionMapper.selectOne(selectionQueryWrapper);
        if (selectionDO != null) {
            throw ServiceException.of(ErrorCodeConstants.HAVE_SELECTED);
        }

        // 课程容量减1
        Integer capacity = scheduleDO.getCapacity();
        if (capacity <= 0) {
            throw ServiceException.of(ErrorCodeConstants.CAPACITY_FULL);
        }
        scheduleDO.setCapacity(--capacity);
        scheduleService.updateById(scheduleDO);

        // 添加选课信息
        selectionDO = SelectionDO.builder()
                .studentNumber(studentEntity.getNumber())
                .studentName(studentEntity.getName())
                .courseNumber(scheduleDO.getCourseNumber())
                .courseName(scheduleDO.getCourseName())
                .teacherName(scheduleDO.getTeacherName())
                .build();
        selectionMapper.insert(selectionDO);
    }

    @Override
    public List<Map<String, Object>> selectByStudentNumber(Integer studentNumber) {
        return selectionMapper.selectByStudentId(studentNumber);
    }

    @Override
    public List<Map<String, Object>> selectList() {
        return selectionMapper.selectList();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void remove(List<Integer> selectionIdList) {
        // 删除选课信息
        selectionMapper.deleteByIds(selectionIdList);
        // 更新排课容量
        scheduleService.updateCapacityBySelectionIdList(selectionIdList);
    }
}
